import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
import json
import os
from typing import Dict, Any


class JsonEditor:
    def __init__(self, parent):
        self.parent = parent
        self.config = None
        self.setup_ui()
        self.json_text = None
        
    def setup_ui(self):
        """设置JSON编辑器界面"""
        # 创建主框架
        self.main_frame = ttk.Frame(self.parent)
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        self.json_text = None

    def _bind_undo_redo(self, widget: tk.Text):
        widget.config(undo=True)
        widget.bind('<Control-z>', self.undo)
        widget.bind('<Control-y>', self.redo)
        widget.bind('<Control-Z>', self.undo)
        widget.bind('<Control-Y>', self.redo)
        
    def load_config(self, config: Dict[str, Any], config_path: str = None):
        """加载配置并显示原始文件格式"""
        self.config = config
        self.config_path = config_path
        self.clear_widgets()
        
        if not config:
            return
            
        # 检查是否是ref引用类型
        if 'ref' in config and isinstance(config['ref'], dict):
            # 处理ref引用，显示被引用的文件内容
            self.create_ref_form(config, config_path)
        else:
            # 创建简单的JSON编辑器
            self.create_json_form(config, config_path)
            
    def create_ref_form(self, config: Dict[str, Any], config_path: str = None):
        """创建ref引用类型的表单"""
        # 显示ref引用信息
        ref_info_frame = ttk.Frame(self.main_frame)
        ref_info_frame.pack(fill=tk.X, pady=(0, 10))
        
        ref = config.get('ref', {})
        ref_text = f"引用配置: {ref.get('standard', '')} {ref.get('edition', '')} {ref.get('cmd', '')}"
        ttk.Label(ref_info_frame, text=ref_text, font=('Arial', 10, 'bold')).pack(anchor=tk.W)
        
        # 显示被引用的文件内容
        try:
            # 根据ref信息构建被引用文件的路径
            current_dir = os.path.dirname(config_path) if config_path else '.'
            frames_root = current_dir
            # 向上查找直到找到frames目录
            while os.path.basename(frames_root) != 'frames' and frames_root != os.path.dirname(frames_root):
                frames_root = os.path.dirname(frames_root)
            
            # 如果没找到frames目录，使用当前目录的父目录
            if os.path.basename(frames_root) != 'frames':
                frames_root = os.path.dirname(current_dir)
                
            # 构建目标文件路径
            target_path = os.path.join(frames_root, ref['standard'], ref['edition'], f"{str(ref['cmd']).lower()}.json")
            
            if os.path.exists(target_path):
                with open(target_path, 'r', encoding='utf-8') as f:
                    referenced_content = f.read()
                
                # 显示被引用的文件内容
                ttk.Label(ref_info_frame, text="被引用文件内容:", font=('Arial', 9, 'bold')).pack(anchor=tk.W, pady=(5, 0))
                
                self.json_text = scrolledtext.ScrolledText(self.main_frame, height=12, wrap=tk.WORD, font=('Consolas', 10))
                self.json_text.pack(fill=tk.BOTH, expand=True)
                self.json_text.insert('1.0', referenced_content)
                self._bind_undo_redo(self.json_text)
            else:
                # 如果被引用文件不存在，显示错误信息
                error_text = f"被引用文件不存在: {target_path}"
                ttk.Label(ref_info_frame, text=error_text, foreground='red').pack(anchor=tk.W, pady=(5, 0))
        except Exception as e:
            # 如果处理ref引用失败，显示错误信息
            error_text = f"处理ref引用失败: {str(e)}"
            ttk.Label(ref_info_frame, text=error_text, foreground='red').pack(anchor=tk.W, pady=(5, 0))

    def create_json_form(self, config: Dict[str, Any], config_path: str = None):
        """创建JSON编辑表单"""
        # 直接创建文本编辑器，不添加外层标签框
        # 使用简单的文本编辑器，设置合适的高度和滚动条
        self.json_text = scrolledtext.ScrolledText(self.main_frame, height=12, wrap=tk.WORD, font=('Consolas', 10))
        self.json_text.pack(fill=tk.BOTH, expand=True)
        
        self._bind_undo_redo(self.json_text)
        
        # 如果有配置文件路径，直接读取原始文件内容
        if config_path and os.path.exists(config_path):
            try:
                with open(config_path, 'r', encoding='utf-8') as f:
                    original_content = f.read()
                self.json_text.insert('1.0', original_content)
            except Exception as e:
                # 如果读取原始文件失败，回退到美化的JSON
                formatted_json = json.dumps(config, indent=2, ensure_ascii=False)
                self.json_text.insert('1.0', formatted_json)
        else:
            # 如果没有配置文件路径，使用美化的JSON
            formatted_json = json.dumps(config, indent=2, ensure_ascii=False)
            self.json_text.insert('1.0', formatted_json)
        
    def get_values(self) -> Dict[str, Any]:
        """获取JSON编辑器的内容"""
        try:
            content = self.json_text.get('1.0', tk.END).strip()
            if not content:
                return {}
            return json.loads(content)
        except json.JSONDecodeError as e:
            # 抛出异常，让调用者处理
            raise json.JSONDecodeError(f"JSON格式错误: {str(e)}", e.doc, e.pos)
        
    def set_values(self, values: Dict[str, Any]):
        """设置JSON编辑器的内容"""
        if values:
            formatted_json = json.dumps(values, indent=2, ensure_ascii=False)
            self.json_text.delete('1.0', tk.END)
            self.json_text.insert('1.0', formatted_json)
                
    def clear(self):
        """清空JSON编辑器"""
        if self.json_text:
            self.json_text.delete(1.0, tk.END)
    
    def set_editable(self, enabled: bool):
        """启用/禁用编辑"""
        try:
            state = tk.NORMAL if enabled else tk.DISABLED
            if self.json_text is not None:
                self.json_text.config(state=state)
        except Exception:
            pass
            
    def undo(self, event=None):
        """撤销操作"""
        try:
            self.json_text.edit_undo()
        except tk.TclError:
            pass  # 没有可撤销的操作
        return "break"  # 阻止默认行为
    
    def redo(self, event=None):
        """重做操作"""
        try:
            self.json_text.edit_redo()
        except tk.TclError:
            pass  # 没有可重做的操作
        return "break"  # 阻止默认行为
            
    def clear_widgets(self):
        """清空所有控件"""
        for widget in self.main_frame.winfo_children():
            widget.destroy()